#include "template_management_view.hpp"

#include "gui/controls/custom_controls.hpp"
#include "gui/ui_component.hpp"
#include "imgui/imgui.h"
#include "json/json.hpp"
#include "imgui/imgui_stdlib.h"
#include "imgui/IconsFontAwesome4.h"
#include "app/app.hpp"
#include "fmt/format.h"
#include "data/template_manager.hpp"
#include "sql/types.hpp"
#include "data/sql_stores.hpp"

#include <vector>
#include <string>
#include <filesystem>
#include <regex>

struct TemplateManagementData {
    bool first_frame = true;
    // std::vector<Tag> all_tags;
    // std::vector<RedMineActivity> all_activities;
    // std::vector<RedMineIssue> all_issues;
    std::list<TemplateInfo> all_template_infos;

    // temp data
    std::string new_template_name;
    int delete_nth = -1;

    void GetTemplateInfos();

    void SaveTemplateInfos();
};

TemplateManagementView::TemplateManagementView() : d{ new TemplateManagementData } {
}

TemplateManagementView::~TemplateManagementView() {
    delete d;
}

unsigned TemplateManagementView::Flags() const {
    return eDialog;
}

template<typename T, typename F>
static int vector_index(const std::vector<T>& vec, F&& f) {
    if (vec.empty())
        return -1;
    const int n = static_cast<int>(std::distance(begin(vec), std::find_if(begin(vec), end(vec), [&](const T& t) { return f(t); })));
    return n == static_cast<int>(size(vec)) ? -1 : n;
}

static double* g_current_edit_value = nullptr;
static void OpenTimeEditor(double* time)
{
    g_current_edit_value = time;
    ImGui::OpenPopup("时间编辑器");
}

static void ShowTimeEditor()
{
    ImGui::SetNextWindowSize(ImVec2(ImGui::GetFontSize() * 20, ImGui::GetFontSize() * 6), ImGuiCond_Always);
    if (ImGui::BeginPopupModal("时间编辑器"))
    {
        static bool show = false;
        static std::string cached_text;

        if (!show) {
            int min = static_cast<int>(*g_current_edit_value * 60);

            if (min < 60)
                cached_text = fmt::format("{}", min);
            else
                cached_text = fmt::format("{}:{:02d}", min / 60, min % 60);

            show = true;
        }

        ImGui::InputText("##时间", &cached_text, ImGuiInputTextFlags_AutoSelectAll);
        HelperMaker("输入时间，格式为:\n 分钟/小时:分钟\n例如:\n 75（75分钟）\n 1:2（1小时2分钟）", true);

        // check input
        static std::regex regex{ R"(\d+|\d+:\d+)" };
        bool acceptable = std::regex_match(cached_text, regex);
        ImGui::BeginDisabled(!acceptable);
        if (ImGui::Button(ICON_FA_CHECK_CIRCLE_O " 确定"))
        {
            // convert to hour and close
            if (auto pos = cached_text.find(':'); pos == std::string::npos)
            {
                *g_current_edit_value = std::stod(cached_text) / 60.0;
            }
            else
            {
                *g_current_edit_value = 1.0 * std::stod(cached_text.substr(0, pos)) + std::stod(cached_text.substr(pos + 1)) / 60.0;
            }
            show = false;
            ImGui::CloseCurrentPopup();
        }
        ImGui::SameLine();
        if (ImGui::Button(ICON_FA_TIMES_CIRCLE_O " 取消"))
        {
            show = false;
            ImGui::CloseCurrentPopup();
        }
        ImGui::EndDisabled();
        ImGui::EndPopup();
    }
}

void TemplateManagementView::Dialog() {
    if (d->first_frame) {
        // d->all_tags = App->Sql()->AllTags();
        // d->all_activities = App->Sql()->AllRedMineActivities();
        // d->all_issues = App->Sql()->AllRedMineIssues();
        d->GetTemplateInfos();
        d->first_frame = false;
        d->delete_nth = -1;
    }

    if (d->delete_nth >= 0) {
        auto it = begin(d->all_template_infos);
        while (d->delete_nth > 0 && end(d->all_template_infos) != it)
        {
            ++it; --d->delete_nth;
        }

        if (it != end(d->all_template_infos))
            d->all_template_infos.erase(it);

        d->delete_nth = -1;
    }

    auto const &all_issues = SqlViewOf(RedMineIssue);
    auto const &all_activities = SqlViewOf(RedMineActivity);
    auto const &all_tags = SqlViewOf(Tag);

    if (ImGui::BeginChild("##ContentArea", ImVec2(0.f, -1.5f * ImGui::GetTextLineHeightWithSpacing()), true)) {

        // 现有模板
        int i = 0;
        const float offset_x = ImGui::GetFontSize() * 10.0f;
        for (auto& x : d->all_template_infos) {
            ImGui::PushID(i++);
            if (ImGui::CollapsingHeader(x.template_name.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
                ImGui::TextUnformatted("模板名称:");
                ImGui::SameLine(offset_x);
                ImGui::InputText("##TemplateNameEdit", &x.template_name);
                ImGui::SameLine();
                if (ImGui::Button(ICON_FA_TRASH " 删除模板"))
                    d->delete_nth = i - 1;

                ImGui::TextUnformatted("默认标题:");
                ImGui::SameLine(offset_x);
                ImGui::InputText("##DefaultTitleEdit", &x.data.default_title);

                ImGui::TextUnformatted("默认耗时(小时):");
                ImGui::SameLine(offset_x);
                ImGui::InputDouble("##DefaultHourEdit", &x.data.default_hour, 0, 0, "%.2f");
                ImGui::SameLine();
                if (ImGui::Button(ICON_FA_PENCIL))
                    OpenTimeEditor(&x.data.default_hour);

                ImGui::TextUnformatted("默认关联任务:");
                ImGui::SameLine(offset_x);
                std::string issue_txt = "未关联问题";
                int id = vector_index(all_issues, [&x](const RedMineIssue& issue) { return issue.issue_id == x.data.default_issue; });
                if (id >= 0) {
                    issue_txt = fmt::format("{} - {}", all_issues[id].project_name, all_issues[id].issue_name);
                }
                if (ImGui::BeginCombo("##关联问题：", issue_txt.c_str())) {
                    for (int j = 0; j < static_cast<int>(all_issues.size()); ++j) {
                        const auto issue_text = fmt::format("{} - {}", all_issues[j].project_name, all_issues[j].issue_name);
                        if (ImGui::Selectable(issue_text.c_str())) {
                            x.data.default_issue = all_issues[j].issue_id;
                        }
                        if (j == id)
                            ImGui::SetItemDefaultFocus();
                    }
                    ImGui::EndCombo();
                }
                ImGui::SameLine();
                if (ImGui::Button(ICON_FA_TRASH " 清除##ISSUE"))
                    x.data.default_issue = 0;

                ImGui::TextUnformatted("默认活动:");
                ImGui::SameLine(offset_x);
                std::string act_txt = "未关联活动";
                int act_id = vector_index(all_activities, [&x](const RedMineActivity& activity) { return activity.act_id == x.data.default_activity; });
                if (act_id >= 0) {
                    act_txt = all_activities[act_id].act_name;
                }
                if (ImGui::BeginCombo("##关联活动：", act_txt.c_str())) {
                    for (int j = 0; j < static_cast<int>(all_activities.size()); ++j) {
                        if (ImGui::Selectable(all_activities[j].act_name.c_str())) {
                            x.data.default_activity = all_activities[j].act_id;
                        }
                        if (j == act_id)
                            ImGui::SetItemDefaultFocus();
                    }
                    ImGui::EndCombo();
                }
                ImGui::SameLine();
                if (ImGui::Button(ICON_FA_TRASH " 清除##ACTIVITY"))
                    x.data.default_activity = 0;

                ImGui::TextUnformatted("默认标签:");
                ImGui::SameLine(offset_x);
                if (ImGui::Button(ICON_FA_PLUS_SQUARE " 添加"))
                    ImGui::OpenPopup("标签列表");

                // 绘制标签信息
                const float max_x = ImGui::GetContentRegionAvail().x;
                float used_x = 0;
                for (const auto& y : x.data.default_tags)
                {
                    int idx = vector_index(all_tags, [y](const Tag& tag) { return y == tag.tag_id; });
                    if (idx < 0)
                        continue;
                    const Tag& tag = all_tags[idx];

                    static const char* btns[]
                    {
                            ICON_FA_TRASH,
                            nullptr
                    };

                    const auto w = ImGui::GetTagRenderWidth(tag, btns);
                    if (used_x > 0 && max_x - used_x > w + 100) {
                        ImGui::SameLine();
                    }
                    else if (used_x > 0) {
                        used_x = 0;
                    }
                    used_x += w;

                    ImGui::RenderTag(tag, btns, [&x](int id, void* data) {
                        const Tag* tag = (Tag*)data;
                        if (id == 0) // Delete
                        {
                            if (tag->tag_level != L_PRIMARY)
                                erase_if(x.data.default_tags, [tag](const auto& x) {return x == tag->tag_id; });
                            else
                                x.data.default_tags.clear();
                        }
                        }, (void*)&tag);
                }
                ImGui::Spacing();

                if (ImGui::BeginPopup("标签列表")) {
                    const bool show_primary = x.data.default_tags.empty() || std::ranges::all_of(x.data.default_tags, [this, &all_tags](auto& x) {
                        int idx = vector_index(all_tags, [x](auto& tag) { return x == tag.tag_id; });
                        return idx < 0 || all_tags[idx].tag_level == L_SECONDARY;
                        });
                    int display_count = 0;
                    for (auto& t : all_tags) {
                        if (show_primary && t.tag_level != L_PRIMARY)
                            continue;
                        if (!show_primary && t.tag_level != L_SECONDARY)
                            continue;
                        if (0 <= vector_index (x.data.default_tags, [id=t.tag_id](auto &x) { return id == x; }))
                            continue;
                        auto display = fmt::format("[{}] {}", (t.tag_level == L_PRIMARY) ? "主" : "次", t.tag_name);
                        if (ImGui::Selectable(display.c_str()) && 0 > vector_index(x.data.default_tags, [&t](auto x) { return x == t.tag_id; })) {
                            x.data.default_tags.emplace_back(t.tag_id);
                        }
                        ++display_count;
                    }
                    if (0 == display_count)
                    {
                        ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 240, 0, 255));
                        ImGui::Selectable(ICON_FA_FROWN_O " 已经没有可添加的标签了");
                        ImGui::PopStyleColor();
                    }
                    ImGui::EndPopup();
                }

                ShowTimeEditor();
            }
            ImGui::PopID();
        }

        if (!d->all_template_infos.empty())
        {
            ImGui::Spacing();
            ImGui::Separator();
        }

        // 固定渲染功能区
        ImGui::TextUnformatted("输入模板名称：");
        ImGui::SameLine();
        ImGui::InputText("##TemplateFilename", &d->new_template_name);
        ImGui::SameLine();
        ImGui::BeginDisabled(d->new_template_name.empty());
        if (ImGui::Button(ICON_FA_PLUS_SQUARE " 创建")) {
            d->all_template_infos.emplace_back(TemplateInfo{ .template_name = d->new_template_name, .data = {} });
            d->new_template_name = "";
        }
        ImGui::EndDisabled();
    }
    ImGui::EndChild();

    ImGui::WindowBottomButtons(2, default_ok_cancel_button_text, [this](int index, void*) {
        d->first_frame = true;
        ImGui::CloseCurrentPopup();
        if (index == 0) // 确定按钮
        {
            TemplateManager::Instence().SetTemplates(d->all_template_infos);
            TemplateManager::Instence().ApplyChange();
        }
        }, nullptr);
}

void TemplateManagementView::RenderContent(ComponentFlag flag) {
    if (flag == eDialog)
        Dialog();
}

const char* TemplateManagementView::GetName(ComponentFlag flag) {
    return flag == eDialog ? MODAL_DIALOG_NAME(TEMPLATE_EDITOR_DIALOG_NAME) : nullptr;
}

void TemplateManagementData::GetTemplateInfos() {
    all_template_infos = TemplateManager::Instence().AllTemplates();
}

void TemplateManagementData::SaveTemplateInfos() {
}
